home *** CD-ROM | disk | FTP | other *** search
/ Total Network Tools 2002 / NextStepPublishing-TotalNetworkTools2002-Win95.iso / Archive / Misc Servers / Zope.exe / ZDOM.PY < prev    next >
Encoding:
Text File  |  2000-07-17  |  20.3 KB  |  628 lines

  1. ##############################################################################
  2. # Zope Public License (ZPL) Version 1.0
  3. # -------------------------------------
  4. # Copyright (c) Digital Creations.  All rights reserved.
  5. # This license has been certified as Open Source(tm).
  6. # Redistribution and use in source and binary forms, with or without
  7. # modification, are permitted provided that the following conditions are
  8. # met:
  9. # 1. Redistributions in source code must retain the above copyright
  10. #    notice, this list of conditions, and the following disclaimer.
  11. # 2. Redistributions in binary form must reproduce the above copyright
  12. #    notice, this list of conditions, and the following disclaimer in
  13. #    the documentation and/or other materials provided with the
  14. #    distribution.
  15. # 3. Digital Creations requests that attribution be given to Zope
  16. #    in any manner possible. Zope includes a "Powered by Zope"
  17. #    button that is installed by default. While it is not a license
  18. #    violation to remove this button, it is requested that the
  19. #    attribution remain. A significant investment has been put
  20. #    into Zope, and this effort will continue if the Zope community
  21. #    continues to grow. This is one way to assure that growth.
  22. # 4. All advertising materials and documentation mentioning
  23. #    features derived from or use of this software must display
  24. #    the following acknowledgement:
  25. #      "This product includes software developed by Digital Creations
  26. #      for use in the Z Object Publishing Environment
  27. #      (http://www.zope.org/)."
  28. #    In the event that the product being advertised includes an
  29. #    intact Zope distribution (with copyright and license included)
  30. #    then this clause is waived.
  31. # 5. Names associated with Zope or Digital Creations must not be used to
  32. #    endorse or promote products derived from this software without
  33. #    prior written permission from Digital Creations.
  34. # 6. Modified redistributions of any form whatsoever must retain
  35. #    the following acknowledgment:
  36. #      "This product includes software developed by Digital Creations
  37. #      for use in the Z Object Publishing Environment
  38. #      (http://www.zope.org/)."
  39. #    Intact (re-)distributions of any official Zope release do not
  40. #    require an external acknowledgement.
  41. # 7. Modifications are encouraged but must be packaged separately as
  42. #    patches to official Zope releases.  Distributions that do not
  43. #    clearly separate the patches from the original work must be clearly
  44. #    labeled as unofficial distributions.  Modifications which do not
  45. #    carry the name Zope may be packaged in any form, as long as they
  46. #    conform to all of the clauses above.
  47. # Disclaimer
  48. #   THIS SOFTWARE IS PROVIDED BY DIGITAL CREATIONS ``AS IS'' AND ANY
  49. #   EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  50. #   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  51. #   PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL DIGITAL CREATIONS OR ITS
  52. #   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  53. #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  54. #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  55. #   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  56. #   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  57. #   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  58. #   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  59. #   SUCH DAMAGE.
  60. # This software consists of contributions made by Digital Creations and
  61. # many individuals on behalf of Digital Creations.  Specific
  62. # attributions are listed in the accompanying credits file.
  63. ##############################################################################
  64. """
  65. DOM implementation in ZOPE : Read-Only methods
  66.  
  67. All standard Zope objects support DOM to a limited extent.
  68. """
  69. import string
  70. import Acquisition
  71.  
  72.  
  73. # Node type codes
  74. # ---------------
  75.  
  76. ELEMENT_NODE       = 1
  77. ATTRIBUTE_NODE     = 2
  78. TEXT_NODE          = 3
  79. CDATA_SECTION_NODE = 4
  80. ENTITY_REFERENCE_NODE = 5
  81. ENTITY_NODE        = 6
  82. PROCESSING_INSTRUCTION_NODE = 7
  83. COMMENT_NODE       = 8
  84. DOCUMENT_NODE      = 9
  85. DOCUMENT_TYPE_NODE = 10
  86. DOCUMENT_FRAGMENT_NODE = 11
  87. NOTATION_NODE      = 12
  88.  
  89. # Exception codes
  90. # ---------------
  91.  
  92. INDEX_SIZE_ERR              = 1
  93. DOMSTRING_SIZE_ERR          = 2
  94. HIERARCHY_REQUEST_ERR       = 3
  95. WRONG_DOCUMENT_ERR          = 4
  96. INVALID_CHARACTER_ERR       = 5
  97. NO_DATA_ALLOWED_ERR         = 6
  98. NO_MODIFICATION_ALLOWED_ERR = 7
  99. NOT_FOUND_ERR               = 8
  100. NOT_SUPPORTED_ERR           = 9
  101. INUSE_ATTRIBUTE_ERR         = 10
  102.  
  103. # Exceptions
  104. # ----------
  105.  
  106. class DOMException(Exception):
  107.     pass
  108. class IndexSizeException(DOMException):
  109.     code = INDEX_SIZE_ERR
  110. class DOMStringSizeException(DOMException):
  111.     code = DOMSTRING_SIZE_ERR
  112. class HierarchyRequestException(DOMException):
  113.     code = HIERARCHY_REQUEST_ERR
  114. class WrongDocumentException(DOMException):
  115.     code = WRONG_DOCUMENT_ERR
  116. class InvalidCharacterException(DOMException):
  117.     code = INVALID_CHARACTER_ERR
  118. class NoDataAllowedException(DOMException):
  119.     code = NO_DATA_ALLOWED_ERR
  120. class NoModificationAllowedException(DOMException):
  121.     code = NO_MODIFICATION_ALLOWED_ERR
  122. class NotFoundException(DOMException):
  123.     code = NOT_FOUND_ERR
  124. class NotSupportedException(DOMException):
  125.     code = NOT_SUPPORTED_ERR
  126. class InUseAttributeException(DOMException):
  127.     code = INUSE_ATTRIBUTE_ERR
  128.  
  129. # Node classes
  130. # ------------
  131.  
  132. class Node:
  133.     """
  134.     Node Interface
  135.     """
  136.  
  137.     __ac_permissions__=(
  138.         ('Access contents information',
  139.             ('getNodeName', 'getNodeValue', 'getParentNode',
  140.             'getChildNodes', 'getFirstChild', 'getLastChild',
  141.             'getPreviousSibling', 'getNextSibling', 'getOwnerDocument',
  142.             'getAttributes', 'hasChildNodes'),
  143.         ),         
  144.     )
  145.  
  146.     # DOM attributes    
  147.     # --------------
  148.     
  149.     def getNodeName(self):
  150.         """The name of this node, depending on its type"""
  151.         return None
  152.  
  153.     def getNodeValue(self):
  154.         """The value of this node, depending on its type"""
  155.         return None
  156.  
  157.     def getParentNode(self):
  158.         """The parent of this node.  All nodes except Document
  159.         DocumentFragment and Attr may have a parent"""
  160.         return None
  161.  
  162.     def getChildNodes(self):
  163.         """Returns a NodeList that contains all children of this node.
  164.         If there are no children, this is a empty NodeList"""
  165.         return NodeList()
  166.  
  167.     def getFirstChild(self):
  168.         """The first child of this node. If there is no such node
  169.         this returns None."""
  170.         return None
  171.  
  172.     def getLastChild(self):
  173.         """The last child of this node. If there is no such node
  174.         this returns None."""
  175.         return None
  176.  
  177.     def getPreviousSibling(self):
  178.         """The node immediately preceding this node.  If
  179.         there is no such node, this returns None."""
  180.         return None
  181.  
  182.     def getNextSibling(self):
  183.         """The node immediately preceding this node.  If
  184.         there is no such node, this returns None."""
  185.         return None
  186.  
  187.     def getAttributes(self):
  188.         """Returns a NamedNodeMap containing the attributes
  189.         of this node (if it is an element) or None otherwise."""
  190.         return None
  191.     
  192.     def getOwnerDocument(self):
  193.         """The Document object associated with this node.
  194.         When this is a document this is None"""
  195.         node = self
  196.         if hasattr(node, 'aq_parent'):
  197.             node = self.aq_parent
  198.             return node.getOwnerDocument()
  199.         return node
  200.         
  201.     # DOM Methods    
  202.     # -----------
  203.     
  204.     def hasChildNodes(self):
  205.         """Returns true if the node has any children, false
  206.         if it doesn't. """
  207.         return len(self.objectIds())
  208.  
  209.  
  210. class Document(Acquisition.Explicit, Node):    
  211.     """
  212.     Document Interface
  213.     """
  214.     
  215.     __ac_permissions__=(
  216.         ('Access contents information',
  217.             ('getImplementation', 'getDoctype', 'getDocumentElement'),
  218.         ),         
  219.     )
  220.     
  221.     # Document Methods
  222.     # ----------------
  223.     
  224.     def getImplementation(self):
  225.         """
  226.         The DOMImplementation object that handles this document.
  227.         """
  228.         return DOMImplementation()
  229.  
  230.     def getDoctype(self):
  231.         """
  232.         The Document Type Declaration associated with this document.
  233.         For HTML documents as well as XML documents without
  234.         a document type declaration this returns null.
  235.         """
  236.         return None
  237.         
  238.     def getDocumentElement(self):
  239.         """
  240.         This is a convenience attribute that allows direct access to
  241.         the child node that is the root element of the document.
  242.         """
  243.         return self.aq_parent
  244.         
  245.     # Node Methods
  246.     # ------------
  247.  
  248.     def getNodeName(self):
  249.         """The name of this node, depending on its type"""
  250.         return '#document'
  251.  
  252.     def getNodeType(self):
  253.         """A code representing the type of the node."""
  254.         return DOCUMENT_NODE 
  255.  
  256.     def getOwnerDocument(self):
  257.         """The Document object associated with this node.
  258.         When this is a document this is None"""
  259.         return self
  260.         
  261.     def getChildNodes(self):
  262.         """Returns a NodeList that contains all children of this node.
  263.         If there are no children, this is a empty NodeList"""
  264.         return NodeList([self.aq_parent])
  265.  
  266.     def getFirstChild(self):
  267.         """The first child of this node. If there is no such node
  268.         this returns None."""
  269.         return self.aq_parent
  270.  
  271.     def getLastChild(self):
  272.         """The last child of this node. If there is no such node
  273.         this returns None."""
  274.         return self.aq_parent
  275.  
  276.     def hasChildNodes(self):
  277.         """Returns true if the node has any children, false
  278.         if it doesn't. """
  279.         return 1
  280.         
  281.  
  282. class DOMImplementation:
  283.     """
  284.     DOMImplementation Interface
  285.     """
  286.  
  287.     __ac_permissions__=(
  288.         ('Access contents information',
  289.             ('hasFeature'),
  290.         ),         
  291.     )
  292.     
  293.     def hasFeature(self, feature, version = None):
  294.         """ 
  295.         hasFeature - Test if the DOM implementation implements a specific
  296.         feature. Parameters: feature The package name of the feature to
  297.         test. In Level 1, the legal values are "HTML" and "XML"
  298.         (case-insensitive). version This is the version number of the
  299.         package name to test. In Level 1, this is the string "1.0". If the
  300.         version is not specified, supporting any version of the feature
  301.         will cause the method to return true. Return Value true if the
  302.         feature is implemented in the specified version, false otherwise.
  303.         """
  304.         feature=string.lower(feature)
  305.         if feature == 'html': return 0
  306.         if feature == 'xml':
  307.             if version is None: return 1
  308.             if version == '1.0': return 1
  309.             return 0
  310.             
  311.  
  312. class Element(Node):
  313.     """
  314.     Element interface
  315.     """
  316.  
  317.     __ac_permissions__=(
  318.         ('Access contents information',
  319.             ('getTagName', 'getAttribute', 'getAttributeNode',
  320.             'getElementsByTagName'),
  321.         ),         
  322.     )
  323.     
  324.     # Element Attributes
  325.     # ------------------
  326.     
  327.     def getTagName(self):
  328.         """The name of the element"""
  329.         return self.__class__.__name__
  330.  
  331.     # Node Attributes
  332.     # ---------------
  333.     
  334.     def getNodeName(self):
  335.         """The name of this node, depending on its type"""
  336.         return self.getTagName()
  337.       
  338.     def getNodeType(self):
  339.         """A code representing the type of the node."""
  340.         return ELEMENT_NODE
  341.     
  342.     def getParentNode(self):
  343.         """The parent of this node.  All nodes except Document
  344.         DocumentFragment and Attr may have a parent"""
  345.         return getattr(self, 'aq_parent', None)
  346.  
  347.     def getChildNodes(self):
  348.         """Returns a NodeList that contains all children of this node.
  349.         If there are no children, this is a empty NodeList"""
  350.         return  NodeList(self.objectValues())
  351.    
  352.     def getFirstChild(self):
  353.         """The first child of this node. If there is no such node
  354.         this returns None"""
  355.         children = self.getChildNodes()
  356.         if children:
  357.             return children._data[0]
  358.         return None
  359.  
  360.     def getLastChild(self):
  361.         """The last child of this node.  If there is no such node
  362.         this returns None."""
  363.         children = self.getChildNodes()
  364.         if children:
  365.             return children._data[-1]
  366.         return None
  367.  
  368.     def getPreviousSibling(self):
  369.         """The node immediately preceding this node.  If
  370.         there is no such node, this returns None."""
  371.         if hasattr(self, 'aq_parent'):
  372.             parent = self.aq_parent
  373.             ids=list(parent.objectIds())
  374.             id=self.id
  375.             if type(id) is not type(''): id=id()
  376.             try: index=ids.index(id)
  377.             except: return None
  378.             if index < 1: return None
  379.             return parent.objectValues()[index-1]
  380.         return None
  381.  
  382.     def getNextSibling(self):
  383.         """The node immediately preceding this node.  If
  384.         there is no such node, this returns None."""
  385.         if hasattr(self, 'aq_parent'):
  386.             parent = self.aq_parent
  387.             ids=list(parent.objectIds())
  388.             id=self.id
  389.             if type(id) is not type(''): id=id()
  390.             try: index=ids.index(id)
  391.             except: return None
  392.             if index >= len(ids)-1: return None
  393.             return parent.objectValues()[index+1]
  394.         return None
  395.       
  396.     # Element Methods
  397.     # ---------------
  398.     
  399.     def getAttribute(self, name):
  400.         """Retrieves an attribute value by name."""
  401.         return None
  402.  
  403.     def getAttributeNode(self, name):
  404.         """ Retrieves an Attr node by name or None if
  405.         there is no such attribute. """
  406.         return None
  407.  
  408.     def getElementsByTagName(self, tagname):
  409.         """ Returns a NodeList of all the Elements with a given tag
  410.         name in the order in which they would be encountered in a
  411.         preorder traversal of the Document tree.  Parameter: tagname
  412.         The name of the tag to match (* = all tags). Return Value: A new
  413.         NodeList object containing all the matched Elements.
  414.         """
  415.         nodeList = []
  416.         for child in self.objectValues():
  417.             if (child.getNodeType()==ELEMENT_NODE and \
  418.                     child.getTagName()==tagname or tagname== '*'):
  419.                 nodeList.append(child)
  420.             if hasattr(child, 'getElementsByTagName'):
  421.                 n1 = child.getElementsByTagName(tagname)
  422.                 nodeList = nodeList + n1._data
  423.         return NodeList(nodeList)
  424.    
  425.  
  426. class ElementWithAttributes(Element):
  427.     """
  428.     Elements that allow DOM access to Zope properties of type 'string'.
  429.     
  430.     Note: This sub-class should only be used by PropertyManagers
  431.     """
  432.     
  433.     def getAttributes(self):
  434.         """Returns a NamedNodeMap containing the attributes
  435.         of this node (if it is an element) or None otherwise."""
  436.         attribs={}
  437.         for p in self._properties:
  438.             if p['type'] == 'string':
  439.                 name=p['id']
  440.                 attrib=Attr(name, self.getProperty(name,'')).__of__(self)
  441.                 attribs[name]=attrib
  442.         return NamedNodeMap(attribs)
  443.    
  444.     def getAttribute(self, name):
  445.         """Retrieves an attribute value by name."""
  446.         if self.getPropertyType(name) == 'string':
  447.             return self.getProperty(name,'')
  448.  
  449.     def getAttributeNode(self, name):
  450.         """Retrieves an Attr node by name or None if
  451.         there is no such attribute. """
  452.         if self.getPropertyType(name) == 'string':
  453.             return Attr(name, self.getProperty(name,'')).__of__(self)
  454.         return None
  455.  
  456.  
  457. class ElementWithTitle(Element):
  458.     """
  459.     Elements that allow DOM access to Zope 'title' property.
  460.     
  461.     Note: Don't use this sub-class for PropertyManagers
  462.     """
  463.     
  464.     def getAttributes(self):
  465.         """Returns a NamedNodeMap containing the attributes
  466.         of this node (if it is an element) or None otherwise."""
  467.         title = self.getAttributeNode('title')
  468.         if title is not None:
  469.             return NamedNodeMap({'title':title})
  470.         return NamedNodeMap()
  471.         
  472.     def getAttribute(self, name):
  473.         """Retrieves an attribute value by name."""
  474.         if name=='title' and hasattr(self.aq_base, 'title'):
  475.             return self.title
  476.         return ''
  477.     
  478.     def getAttributeNode(self, name):
  479.         """Retrieves an Attr node by name or None if
  480.         there is no such attribute. """
  481.         value=self.getAttribute(name)
  482.         if value:
  483.             return Attr(name, value).__of__(self)
  484.         return None
  485.  
  486.             
  487. class Root(ElementWithAttributes):
  488.     """
  489.     The top-level Zope object.
  490.     """
  491.     
  492.     def getOwnerDocument(self):
  493.         """
  494.         """
  495.         return Document().__of__(self)
  496.         
  497.  
  498. class NodeList:
  499.     """NodeList interface - Provides the abstraction of an ordered
  500.     collection of nodes.
  501.     
  502.     Python extensions: can use sequence-style 'len', 'getitem', and
  503.     'for..in' constructs.
  504.     """
  505.  
  506.     # The security machinery is not willing to treat this like a
  507.     # list just because we act like one. We need to assert that
  508.     # its ok to allow access to items in the nodelist.
  509.     __allow_access_to_unprotected_subobjects__=1
  510.  
  511.     def __init__(self,list=None):
  512.         self._data = list or []
  513.     
  514.     def __getitem__(self, index):
  515.         return self._data[index]
  516.         
  517.     def item(self, index):
  518.         """Returns the index-th item in the collection"""
  519.         try: return self._data[index]    
  520.         except IndexError: return None
  521.          
  522.     def getLength(self):
  523.         """The length of the NodeList"""
  524.         return len(self._data)
  525.     
  526.     __len__=getLength
  527.  
  528.  
  529. class NamedNodeMap:
  530.     """
  531.     NamedNodeMap interface - Is used to represent collections
  532.     of nodes that can be accessed by name.  NamedNodeMaps are not
  533.     maintained in any particular order.
  534.     
  535.     Python extensions: can use sequence-style 'len', 'getitem', and
  536.     'for..in' constructs, and mapping-style 'getitem'.
  537.     """
  538.  
  539.     # Tell the security machinery to allow access to items.
  540.     __allow_access_to_unprotected_subobjects__=1
  541.     
  542.     def __init__(self, data=None):
  543.         if data is None : data = {}
  544.         self._data = data
  545.  
  546.     def item(self, index):
  547.         """Returns the index-th item in the map"""
  548.         try: return self._data.values()[index]
  549.         except IndexError: return None
  550.         
  551.     def __getitem__(self, key):
  552.         if type(key)==type(1):
  553.             return self._data.values()[key]
  554.         else:
  555.             return self._data[key]
  556.             
  557.     def getLength(self):
  558.         """The length of the NodeList"""
  559.         return len(self._data)
  560.     
  561.     __len__ = getLength
  562.     
  563.     def getNamedItem(self, name):
  564.         """Retrieves a node specified by name. Parameters:
  565.         name Name of a node to retrieve. Return Value A Node (of any
  566.         type) with the specified name, or None if the specified name
  567.         did not identify any node in the map.
  568.         """
  569.         if self._data.has_key(name): 
  570.             return self._data[name]
  571.         return None
  572.  
  573.  
  574. class Attr(Acquisition.Implicit, Node):
  575.     """
  576.     Attr interface - The Attr interface represents an attriubte in an
  577.     Element object. Attr objects inherit the Node Interface
  578.     """
  579.  
  580.     def __init__(self, name, value):
  581.         self.name = name
  582.         self.value = value
  583.         self.specified = 1
  584.         
  585.     def getNodeName(self):
  586.         """The name of this node, depending on its type"""
  587.         return self.name
  588.  
  589.     def getName(self):
  590.         """Returns the name of this attribute."""
  591.         return self.name
  592.     
  593.     def getNodeValue(self):
  594.         """The value of this node, depending on its type"""
  595.         return self.value
  596.  
  597.     def getNodeType(self):
  598.         """A code representing the type of the node."""
  599.         return ATTRIBUTE_NODE
  600.  
  601.     def getSpecified(self):
  602.         """If this attribute was explicitly given a value in the
  603.         original document, this is true; otherwise, it is false."""
  604.         return self.specified
  605.         
  606.         
  607.